﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Data;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Objects;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Common.Framework.EntityMaster;
using Tools.Framework;

namespace Common.Framework.CommonDAL
{
    /// <summary>
    ///  业务层基类
    /// </summary>
    /// <typeparam name="TEntity">实体 TEntity</typeparam>
    /// <typeparam name="TDbEntitie"></typeparam>
    [Export]
    public class ServiceBase<TDbEntitie, TEntity> : ServiceAdapter<TDbEntitie>
        where TDbEntitie : DbContext, new()
        where TEntity : class, new()
    {
        #region message

        //private const string InsertFail = "新增操作未能完成，失败原因参见系统错误日志！";
        //private const string UpdateFail = "更新操作未能完成，失败原因参见系统错误日志！";
        //private const string DeleteFail = "删除操作未能完成，失败原因参见系统错误日志！";
        //private const string OtherFail = "操作失败！";

        #endregion



        public DbConnection DbConnection
        {
            get { return new TDbEntitie().Database.Connection; }
        }


        #region Insert

        /// <summary>
        /// 上下文实体
        /// </summary>
        [Obsolete("框架不允许使用该函数")]
        public void ExposedDbContext(Action<TDbEntitie> callback)
        {
            try
            {
                base.Adapter.ExposedDbContext(callback);
            }
            catch (Exception )
            {
                throw;
            }
           
        }

        /// <summary>
        ///     添加 Entity
        /// </summary>
        /// <param name="entity">TEntity entity</param>
        /// <returns>bool</returns>
        public virtual bool AddObject(TEntity entity)
        {
            try
            {
                object result = base.ExecuteService(() => base.Adapter.AddObject(entity), false);
                return ((int)result) >= 0;
            }
            catch (Exception )
            {
                throw;
            }
        }

        /// <summary>
        ///     批量添加 entity
        /// </summary>
        /// <param name="data"><![CDATA[IEnumerable<TEntity>集合]]></param>
        /// <returns>bool</returns>
        public virtual bool AddObject(IEnumerable<TEntity> data)
        {
            try
            {
                object result = base.ExecuteService(() => base.Adapter.AddObject(data), true);
                return ((int)result) >= 0;
            }
            catch (Exception ex)
            {
                throw;
            }
        }


        /// <summary>
        ///     批量添加 entity
        /// </summary>
        /// <param name="data"><![CDATA[IEnumerable<TEntity>集合]]></param>
        /// <returns>bool</returns>
        public virtual bool AddOrUpdateObject(IEnumerable<TEntity> data)
        {
            try
            {
                object result = base.ExecuteService(() => base.Adapter.AddOrUpdateObject(data), true);
                return ((int)result) >= 0;
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        /// <summary>
        ///     批量添加 entity
        /// </summary>
        /// <param name="data"><![CDATA[IEnumerable<TEntity>集合]]></param>
        /// <returns>bool</returns>
        public virtual bool AddOrUpdateObject(TEntity entity)
        {
            try
            {
                object result = base.ExecuteService(() => base.Adapter.AddOrUpdateObject(entity), true);
                return ((int)result) >= 0;
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        #endregion

        #region Update

        /// <summary>
        ///     修改 Entity
        /// </summary>
        /// <param name="entity">TEntity entity</param>
        /// <returns>bool</returns>
        public virtual bool UpdateObject(TEntity entity)
        {
            try
            {
                object result = base.ExecuteService(() => base.Adapter.UpdateObject(entity), false);
                return ((int)result) >= 0;
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        /// <summary>
        ///     批量修改 Entity
        /// </summary>
        /// <param name="data"><![CDATA[IEnumerable<TEntity> 集合]]></param>
        /// <returns>bool</returns>
        public virtual bool UpdateObject(IEnumerable<TEntity> data)
        {
            try
            {
                object result = base.ExecuteService(() => base.Adapter.UpdateObject(data), true);
                return ((int)result) >= 0;
            }
            catch (Exception ex)
            {
                throw;
            }
        } 

        #endregion

        #region Update operation for EntityFramework Extensions

        /// <summary>
        ///     更新实体对象
        /// </summary>
        /// <typeparam name="TEntity">Class</typeparam>
        /// <param name="filterExpression">过滤条件</param>
        /// <param name="updateExpression">更新实体对象</param>
        /// <returns>bool</returns>
        public bool UpdateObject(Expression<Func<TEntity, bool>> filterExpression,
            Expression<Func<TEntity, TEntity>> updateExpression)
        {
            try
            {
                object result = base.ExecuteService(
                    () => base.Adapter.UpdateObject(filterExpression, updateExpression), false);
                return ((int)result) >= 0;
            }
            catch (Exception ex)
            {
                LogHelper.Write(ex);
                throw;
            }
        }


        /// <summary>
        ///     批量更新实体对象
        /// </summary>
        /// <typeparam name="TEntity">Class</typeparam>
        /// <param name="updateExpressions">更新表达式集合</param>
        /// <returns>bool</returns>
        public bool UpdateObject(IEnumerable<UpdateExpressionsEntity<TEntity>> updateExpressions)
        {
            try
            {
                object result = base.ExecuteService(() => base.Adapter.UpdateObject(updateExpressions), false);
                return ((int)result) >= 0;
            }
            catch (Exception ex)
            {
                LogHelper.Write(ex);
                throw;
            }
        }

        #endregion

        #region Delete

        /// <summary>
        ///     删除 Entity
        /// </summary>
        /// <param name="entity">TEntity entity</param>
        public virtual bool DeleteObject(TEntity entity)
        {
            try
            {
                object result = base.ExecuteService(() => base.Adapter.DeleteObject(entity), false);
                return (int)result > 0;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        ///     批量删除对象
        /// </summary>
        /// <param name="data">要删除的数据集合</param>
        /// <param name="isOpenTransaction">是否开启分布式事务</param>
        public virtual bool DeleteObject(IEnumerable<TEntity> data)
        {
            try
            {
                var result = base.ExecuteService(() => base.Adapter.DeleteObject(data), true);
                return (int)result > 0;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        ///     批量删除对象
        /// </summary>
        /// <param name="expression">删除条件</param>
        public virtual bool DeleteObject(Expression<Func<TEntity, bool>> expression)
        {
            try
            {
                var result = base.ExecuteService(() => base.Adapter.DeleteObject(expression), true);
                return (int)result > 0;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        #region Delete operation for EntityFramework Extensions



        #endregion

        #region Select

        /// <summary>
        ///     获取单个实体
        /// </summary>
        /// <param name="where">Lamdia 表达式</param>
        /// <param name="path">外键对象路径</param>
        /// <returns>TEntity</returns>
        public virtual TEntity GetEntity(Expression<Func<TEntity, bool>> where, params string[] path)
        {
            return base.Adapter.GetEntity(where, path);
        }

        /// <summary>
        ///     获取单个实体
        /// </summary>
        /// <typeparam name="TDEntity">DTO 对象</typeparam>
        /// <param name="where">Lamdia 表达式</param>
        /// <param name="path">外键对象路径</param>
        /// <returns>DTO</returns> 
        public virtual TDEntity GetTDEntity<TDEntity>(Expression<Func<TEntity, bool>> where, params string[] path)
        {
            return ObjectMapper.Mapper<TEntity, TDEntity>(this.GetEntity(where, path));
        }

        /// <summary>
        /// 查询对象集合 返回指定数量的数据
        /// </summary>
        /// <typeparam name="TEntity">
        /// class TEntity
        /// </typeparam>
        /// <param name="expression">
        /// lamda 表达式
        /// </param>
        /// <param name="sortField">
        /// 排序字段 默认为升序排列
        /// </param>
        /// <param name="totalRecord">
        /// 需要返回的数据条数
        /// </param>
        /// <param name="includePath">
        /// 关联路径
        /// </param>
        /// <returns>
        /// List{TEntity}
        /// </returns>
        [Obsolete("框架不允许使用该函数")]
        public List<TEntity> GetTopList(
            Expression<Func<TEntity, bool>> expression,
            string sortField,
            int totalRecord,
            params string[] includePath)
        {
            return this.Adapter.GetTopList(expression, sortField, totalRecord, includePath).ToList();
        }

        /// <summary>
        /// 查询对象集合 返回指定数量的数据
        /// </summary>
        /// <typeparam name="TEntity">
        /// class TEntity
        /// </typeparam>
        /// <param name="expression">
        /// lamda 表达式
        /// </param>
        /// <param name="sortField">
        /// 排序字段 默认为升序排列
        /// </param>
        /// <param name="isDesc">
        /// 是否降序排列
        /// </param>
        /// <param name="totalRecord">
        /// 需要返回的数据条数
        /// </param>
        /// <param name="includePath">
        /// 关联路径
        /// </param>
        /// <returns>
        /// List{TEntity}
        /// </returns>
        [Obsolete("框架不允许使用该函数")]
        public List<TEntity> GetTopList(
            Expression<Func<TEntity, bool>> expression,
            string sortField,
            bool isDesc,
            int totalRecord,
            params string[] includePath)
        {
            return this.Adapter.GetTopList(expression, sortField, isDesc, totalRecord, includePath).ToList();
        }


        /// <summary>
        ///     获取实体集合
        /// </summary>
        /// <param name="where">获取实体集合查询条件</param>
        /// <param name="path">外键对象路径</param>
        /// <returns><![CDATA[List<TEntity>]]></returns>
        [Obsolete("框架不允许使用该函数")]
        public virtual List<TEntity> GetList(Expression<Func<TEntity, bool>> where, params string[] path)
        {
            return base.Adapter.GetList(@where, path).ToList();
        }

        /// <summary>
        /// 获取实体集合
        /// </summary>
        /// <param name="entsql">
        /// The entsql.
        /// </param>
        /// <param name="parameters">
        /// The parameters.
        /// </param>
        /// <param name="includePath">
        /// The include Path.
        /// </param>
        /// <returns>
        /// <![CDATA[List<TEntity>]]>
        /// </returns> 
        public virtual List<TEntity> GetList(string entsql,
            ObjectParameter[] parameters,
            params string[] includePath)
        {
            return base.Adapter.GetList<TEntity>(entsql, parameters, includePath).ToList();
        }


        /// <summary>
        ///     获取实体集合
        /// </summary>
        /// <typeparam name="TDEntity">DTO对象</typeparam>
        /// <param name="where">获取实体集合查询条件</param>
        /// <param name="path">外键对象路径</param>
        /// <returns><![CDATA[List<TDEntity> ]]></returns>
        [Obsolete("框架不允许使用该函数")]
        public virtual List<TDEntity> GetTDList<TDEntity>(Expression<Func<TEntity, bool>> where, params string[] path)
        {
            return ObjectMapper.Mapper<List<TEntity>, List<TDEntity>>(this.GetList(where, path));
        }


        /// <summary>
        ///     查询分页对象集合
        /// </summary>
        /// <typeparam name="TEntity">class TEntity</typeparam>
        [Obsolete("框架不允许使用该函数")]
        public virtual void GetPager(PageData<TEntity> pager)
        {
            long totalCount = 0;
            object result = base.ExecuteService(() => pager.OrderFiledList == null ? base.Adapter.GetPager(
                pager.Where,
                pager.PageIndex,
                pager.PageSize,
                ref totalCount,
                pager.OrderField,
                pager.IsDesc,
                pager.Include) : base.Adapter.GetPager(
                pager.Where,
                pager.PageIndex,
                pager.PageSize,
                ref totalCount,
                pager.OrderField,
                pager.IsDesc,
                pager.Include));
            pager.TotalCount = totalCount;
            pager.PageCount = Convert.ToInt32(totalCount / pager.PageSize) + (totalCount % pager.PageSize > 0 ? +1 : +0);
            pager.Data = result as List<TEntity>;
        }





        /// <summary>
        ///     查询分页对象集合
        /// </summary>
        /// <typeparam name="TEntity">class TEntity</typeparam>
        [Obsolete("框架不允许使用该函数")]
        public virtual void GetPager2(PageData<TEntity> pager)
        {
            long totalCount = 0;
            object result = base.ExecuteService(() => base.Adapter.GetPager<TEntity>(
                pager.Where,
                pager.PageIndex,
                pager.PageSize,
                ref totalCount,
                pager.OrderFiledList,
                pager.Include));
            pager.TotalCount = totalCount;
            pager.Data = result as List<TEntity>;
        }


        #endregion

        #region Other

        /// <summary>
        ///     创建一个原始 SQL 查询，该查询将返回给定泛型类型的元素。类型可以是包含与从查询返回的列名匹配的属性的任何类型，也可以是简单的基元类型
        /// </summary>
        /// <typeparam name="TEntity2">TEntity</typeparam>
        /// <param name="sql">SQL 查询语句</param>
        /// <param name="parameter">查询参数</param>
        /// <returns><![CDATA[IEnumerable<TEntity2>]]></returns>
        public IEnumerable<TEntity2> ExecuteSqlCommand<TEntity2>(string sql, params object[] parameter) where TEntity2 : class
        {
            object result = base.ExecuteService(() => base.Adapter.SqlQuery<TEntity2>(sql, parameter));
            return result as List<TEntity2>;
        }

        /// <summary>
        ///     对数据库执行给定的 DDL/DML 命令。
        /// </summary>
        /// <param name="sql">命令字符串。</param>
        /// <param name="parmaeters">要应用于命令字符串的参数。SqlParameter</param>
        /// <returns>bool</returns>
        public bool ExecuteSqlCommand(string sql, params object[] parmaeters)
        {
            try
            {
                object result = base.ExecuteService(() => base.Adapter.ExecuteSqlCommand(sql, parmaeters), false);
                return ((int)result) >= 0;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        ///     对数据库执行给定的 DDL/DML 命令。
        /// </summary>
        /// <param name="sql">命令字符串。</param>
        /// <param name="parmaeters">要应用于命令字符串的参数。SqlParameter</param>
        /// <returns>bool</returns>
        public DataSet ExecuteSqlCommandToTables(string sql, params object[] parmaeters)
        {
            try
            {
                DataSet result = (DataSet)base.ExecuteService(() => base.Adapter.ExecuteSqlCommandToTables(sql, parmaeters), false);
                return result;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        /// <summary>
        ///     执行存储过程
        /// </summary>
        /// <param name="procedureName">存储过程名称</param>
        /// <param name="parmaeters">要应用于存储过程的字符串的参数。 SqlParameter</param>
        /// <returns>dynamic</returns>
        public DataSet ExecuteProcedure(string procedureName, params object[] parmaeters)
        {
            try
            {
                object result = base.ExecuteService(() => base.Adapter.ExecuteProcedure(procedureName, parmaeters),
                    false);
                return result as DataSet;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        ///     根据条件判断是否存在
        /// </summary>
        /// <param name="where">查询条件</param>
        /// <param name="path">外键对象路径</param>
        /// <returns>bool</returns>
        public virtual bool Exists(Expression<Func<TEntity, bool>> where, params string[] path)
        {
            return this.GetEntity(where, path) != null;
        }


        /// <summary>
        ///     根据条件判断是否存在
        /// </summary>
        /// <param name="where">查询条件</param>
        /// <param name="path">外键对象路径</param>
        /// <returns>bool</returns>
        public virtual int Count(Expression<Func<TEntity, bool>> where, params string[] path)
        {
            return base.Adapter.Count(where, path);
        }

        #endregion



    }
}
